using System;
using System.Collections.Generic;

namespace SoftwareMonkeys.Scriptech.Projects
{
	public class ProjectBuildOrderDetector
	{
		public string StoreName = String.Empty;
		public string GroupName = String.Empty;
		public string ProjectName = String.Empty;
		
		public ProjectAssembly[] GetBuildOrder(ProjectAssembly[] assemblies)
		{
			List<ProjectAssembly> buildOrder = new List<ProjectAssembly>();
			
			foreach (ProjectAssembly assembly in assemblies)
			{
				if (!Contains(buildOrder.ToArray(), assembly))
					AddAssemblyToList(buildOrder, assembly);
			}
			
			return buildOrder.ToArray();
		}
		
		public string[] GetBuildOrderStrings(ProjectAssembly[] assemblies)
		{
			ProjectAssembly[] buildOrder = GetBuildOrder(assemblies);
			
			List<string> strings = new List<string>();
			
			foreach (ProjectAssembly assembly in buildOrder)
			{
				strings.Add(assembly.Name);
			}
			
			return strings.ToArray();
		}
		
		public void AddAssemblyToList(List<ProjectAssembly> buildOrder, ProjectAssembly assembly)
		{
			for (int i = 0; i < buildOrder.Count; i++)
			{
				ProjectAssembly a = buildOrder[i];
				
				// If the assembly is not already in the build order list
				if (!Contains(buildOrder.ToArray(), assembly))
				{
					// If the assembly at this position references the one provided then insert the provided one before it
					if (Contains(a.ReferencedAssemblies, assembly.Name))
					{
						buildOrder.Insert(i, assembly);
						
						i++;
					}
				}
			}
			
			// If the provided assembly isn't in the list then add it to the end
			if (!Contains(buildOrder.ToArray(), assembly))
				buildOrder.Add(assembly);
		}
		
		public bool Contains(string[] referencedAssemblyNames, string assemblyName)
		{
			foreach (string referencedAssemblyName in referencedAssemblyNames)
			{
				 if (Matches(referencedAssemblyName, assemblyName))
					return true;
			}
			
			return false;
		}
		
		public bool Matches(string name1, string name2)
		{
			if (GroupName == String.Empty)
				throw new Exception("The GroupName property must be set.");
			
			if (ProjectName == String.Empty)
				throw new Exception("The ProjectName property must be set.");
			
			string strippedName1 = name1.ToLower();
			strippedName1 = strippedName1.Replace(GroupName.ToLower() + ".", "");
			strippedName1 = strippedName1.Replace(ProjectName.ToLower() + ".", "");
			
			string strippedName2 = name2.ToLower();
			strippedName2 = strippedName2.Replace(GroupName.ToLower() + ".", "");
			strippedName2 = strippedName2.Replace(ProjectName.ToLower() + ".", "");
			
			return strippedName1 == strippedName2;
		}
		
		public bool Contains(ProjectAssembly[] assemblies, ProjectAssembly assembly)
		{
			foreach (ProjectAssembly a in assemblies)
			{
				if (a.Name == assembly.Name)
					return true;
			}
			
			return false;
		}
	}
}

